const md5 = require("md5");
const fs = require("fs");
const got = require("got");
const Joi = require("joi");
const svgCaptcha = require("svg-captcha");
const API = require("co-wechat-api");
const uuid = require("uuid/v4");
const moment = require("moment");
const Code = require("./../../../../lib/wxa/code.class");

module.exports = class extends doodoo.Controller {
    /**
     *
     * @api {get} /home/public/captcha 客户登录验证码
     * @apiDescription 客户登录验证码
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiSuccess {String} svg svg图片
     * @apiSuccess {String} uuid 验证码随机码
     *
     * @apiSampleRequest /home/public/captcha
     *
     */
    async captcha() {
        const captcha = svgCaptcha.create({ width: 100, height: 40 });
        const ip = this.get("X-Real-IP") || this.ip;
        const verify = await this.model("verify")
            .forge({
                value: captcha.text.toLowerCase(),
                uuid: uuid(),
                ip: ip
            })
            .save();

        this.success({
            svg: captcha.data,
            uuid: verify.uuid
        });
    }

    /**
     *
     * @api {get} /home/public/ads 获取广告列表
     * @apiDescription 获取广告列表
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiParam {String} type 广告类型
     * @apiParam {String} limit 广告数量
     *
     * @apiSampleRequest /home/public/ads
     *
     */
    async ads() {
        const { type = 1, limit = 3 } = this.query;
        const ads = await this.model("ads")
            .query(qb => {
                qb.where("type", type);
                qb.orderBy("rank", "desc");
                qb.limit(limit);
            })
            .fetchAll();

        this.success(ads);
    }

    /**
     *
     * @api {post} /home/public/sendSmsCode 发送短信验证码
     * @apiDescription 发送短信验证码
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiParam {String} phone 手机号
     *
     * @apiSampleRequest /home/public/sendSmsCode
     *
     */
    async sendSmsCode() {
        await this.validate(this.post, {
            phone: Joi.string()
                .required()
                .length(11)
        });

        const { phone } = this.post;
        const code = this.randomCode(6);
        const ip = this.get("X-Real-IP") || this.ip;

        const verifyIpCount = await this.model("verify")
            .query(qb => {
                qb.where("ip", "=", ip);
                qb.whereNotNull("phone");
                qb.where(
                    "created_at",
                    ">",
                    `${moment().format("YYYY-MM-DD")} 00:00:00`
                );
            })
            .count();
        if (verifyIpCount > process.env.VERIFY_MAXIP) {
            this.fail(
                "超出验证码发送最大限制，如需帮助请联系客服",
                "超出验证码发送最大限制，如需帮助请联系客服"
            );
            return;
        }

        const verifyPhoneCount = await this.model("verify")
            .query(qb => {
                qb.where("phone", "=", phone);
                qb.where(
                    "created_at",
                    ">",
                    `${moment().format("YYYY-MM-DD")} 00:00:00`
                );
            })
            .count();
        if (verifyPhoneCount > process.env.VERIFY_MAXPHONE) {
            this.fail(
                "超出验证码发送最大限制，如需帮助请联系客服",
                "超出验证码发送最大限制，如需帮助请联系客服"
            );
            return;
        }

        const verify = await this.model("verify")
            .forge({
                value: code,
                uuid: uuid(),
                ip: ip,
                phone: phone
            })
            .save();

        try {
            // 发送验证码
            await this.sendSms(phone, code);
        } catch (err) {
            this.fail(err.message);
            return;
        }

        this.success(
            {
                uuid: verify.uuid
            },
            "发送成功"
        );
    }

    /**
     *
     * @api {post} /home/public/login 客户登录
     * @apiDescription 客户登录授权
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiParam {Phone} phone 客户手机号
     * @apiParam {String} password 客户密码
     * @apiParam {String} captcha 验证码
     * @apiParam {String} captchaUuid 验证码随机码
     *
     * @apiSuccess {String} token jwt加密码
     * @apiSuccess {Json} custom 客户信息
     *
     * @apiSampleRequest /home/public/login
     *
     */
    async login() {
        await this.validate(this.post, {
            phone: Joi.string()
                .required()
                .length(11),
            password: Joi.string().required(),
            captcha: Joi.string().required(),
            captchaUuid: Joi.string().required()
        });

        const { phone, password, captcha, captchaUuid } = this.post;
        const ip = this.get("X-Real-IP") || this.ip;
        const verify = await this.model("verify")
            .query({
                where: {
                    uuid: captchaUuid,
                    value: captcha,
                    status: 0
                }
            })
            .fetch();
        if (!verify) {
            this.fail("验证码有误");
            return;
        }
        // 验证码核销
        await this.model("verify")
            .forge({
                id: verify.id,
                status: 1
            })
            .save();

        const custom = await this.model("custom")
            .query({
                where: {
                    phone: phone,
                    password: md5(password)
                }
            })
            .fetch();
        if (!custom) {
            this.fail("账号密码有误");
            return;
        }
        // 记录登录IP
        await this.model("custom_log")
            .forge({
                custom_id: custom.id,
                ip: ip,
                info: "登录"
            })
            .save();

        const token = this.jwtSign(custom);
        this.success({ token, custom });
    }

    /**
     *
     * @api {post} /home/public/register 客户注册
     * @apiDescription 客户注册
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiParam {Phone} phone 客户手机号
     * @apiParam {String} password 客户密码
     * @apiParam {String} nickname 客户用户名
     * @apiParam {String} phoneCode 验证码
     * @apiParam {String} phoneCodeUuid 验证码随机码
     *
     * @apiSuccess {String} data 用户注册成功
     *
     * @apiSampleRequest /home/public/register
     *
     */
    async register() {
        await this.validate(this.post, {
            phone: Joi.string()
                .required()
                .length(11),
            password: Joi.string().required(),
            phoneCode: Joi.string().required(),
            phoneCodeUuid: Joi.string().required(),
            nickname: Joi.string().required()
        });

        const {
            phone,
            password,
            phoneCode,
            phoneCodeUuid,
            nickname,
            email
        } = this.post;
        const wxUserToken = this.get("wxUserToken");
        const _domain = this.get("X-Host") || "www.doodooke.com";
        const _domains = _domain.split(".");
        _domains.shift();
        const domain = _domains.join(".");

        const verify = await this.model("verify")
            .query({
                where: {
                    uuid: phoneCodeUuid,
                    value: phoneCode,
                    phone: phone,
                    status: 0
                }
            })
            .fetch();
        if (!verify) {
            this.fail("手机验证码有误");
            return;
        }

        // 验证码核销
        await this.model("verify")
            .forge({
                id: verify.id,
                status: 1
            })
            .save();

        let custom = await this.model("custom")
            .query({ where: { phone: phone } })
            .fetch();
        if (custom) {
            this.fail("手机号已存在，请更换手机号注册");
            return;
        }

        const data = {
            nickname: nickname,
            phone: phone,
            email: email,
            password: md5(password),
            password_org: password,
            domain: domain,
            status: 1
        };

        custom = await this.model("custom")
            .forge(data)
            .save();
        if (wxUserToken) {
            const decoded = this.jwtVerify(wxUserToken);
            await this.model("wx_user")
                .forge({ id: decoded.id, custom_id: custom.id })
                .save();
            await this.model("custom")
                .forge({ id: custom.id, avater_url: decoded.headimgurl })
                .save();
        }

        this.hook.run("analysis", "custom");
        this.success();
    }

    /**
     *
     * @api {post} /home/public/resetPwd 客户重置密码
     * @apiDescription 客户重置密码
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiParam {Phone} phone 客户手机号
     * @apiParam {String} password 客户密码
     * @apiParam {String} phoneCode 短信验证码
     * @apiParam {String} phoneCodeUuid 短信验证码随机码
     * @apiParam {String} captcha 验证码随机码
     * @apiParam {String} captchaUuid 验证码随机码
     *
     * @apiSuccess {String} data 用户密码重置成功
     *
     * @apiSampleRequest /home/public/resetPwd
     *
     */
    async resetPwd() {
        await this.validate(this.post, {
            phone: Joi.string()
                .required()
                .length(11),
            password: Joi.string().required(),
            phoneCode: Joi.string().required(),
            phoneCodeUuid: Joi.string().required(),
            captcha: Joi.string().required(),
            captchaUuid: Joi.string().required()
        });

        const {
            phone,
            password,
            phoneCode,
            phoneCodeUuid,
            captcha,
            captchaUuid
        } = this.post;

        // 图片验证码
        const verifyCaptcha = await this.model("verify")
            .query({
                where: {
                    uuid: captchaUuid,
                    value: captcha,
                    status: 0
                }
            })
            .fetch();
        if (!verifyCaptcha) {
            this.fail("验证码有误");
            return;
        }
        // 验证码核销
        await this.model("verify")
            .forge({
                id: verifyCaptcha.id,
                status: 1
            })
            .save();

        // 短信验证码
        const verify = await this.model("verify")
            .query({
                where: {
                    uuid: phoneCodeUuid,
                    value: phoneCode,
                    status: 0
                }
            })
            .fetch();
        if (!verify) {
            this.fail("手机验证码有误");
            return;
        }
        // 验证码核销
        await this.model("verify")
            .forge({
                id: verify.id,
                status: 1
            })
            .save();

        const custom = await this.model("custom")
            .query({ where: { phone: phone } })
            .fetch();
        if (!custom) {
            this.fail("手机号未注册");
            return;
        }

        await this.model("custom")
            .forge({
                id: custom.id,
                password: md5(password),
                password_org: password
            })
            .save();

        this.success("success", "用户密码重置成功");
    }

    /**
     *
     * @api {get} /home/public/logo 获取浏览器版权logo
     * @apiDescription 获取浏览器版权logo
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiSampleRequest /home/public/logo
     *
     */
    async logo() {
        this.status = 200;
        this.set("Content-Type", "image/jpg");
        this.body = fs.createReadStream("data/logo/www.png");
    }

    /**
     *
     * @api {get} /home/public/wxaLogo 获取小程序版权logo
     * @apiDescription 获取小程序版权logo
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiParam {String} appid 小程序appid
     *
     * @apiSampleRequest /home/public/wxaLogo
     *
     */
    async wxaLogo() {
        // const referer = this.get("Referer");
        // const referers = referer.substr(26).split("/");
        // const WxaAppId = referers[0];
        let WxaAppId = this.query.appid;
        if (!WxaAppId) {
            const referer = this.query.Referer || this.get("Referer");
            const reg = new RegExp("https://servicewechat.com/(\\w*)/(\\w*)/");
            if (!referer.match(reg)) {
                console.log("Referer有误");
                return;
            }
            WxaAppId = RegExp.$1;
        }

        if (!WxaAppId) {
            console.log("Referer有误");
            return;
        }

        const wxa = await this.model("wxa")
            .query({
                where: {
                    authorizer_appid: WxaAppId
                }
            })
            .fetch();
        if (!wxa) {
            console.log("小程序不存在");
            return;
        }
        const uncopyright = await this.model("uncopyright")
            .query(qb => {
                qb.where("app_id", wxa.app_id);
            })
            .fetch();
        if (uncopyright && uncopyright.status) {
            this.status = 200;
            this.set("Content-Type", "image/jpg");
            this.body = got.stream.get(uncopyright.logo);
            return;
        }

        this.status = 200;
        this.set("Content-Type", "image/jpg");
        this.body = fs.createReadStream("data/logo/wxa.png");
    }

    /**
     *
     * @api {get} /home/public/fetchWxImg 获取微信图片
     * @apiDescription 获取微信图片
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiParam {String} imageUrl 图片链接
     *
     * @apiSampleRequest /home/public/fetchWxImg
     *
     */
    async fetchWxImg() {
        const { imageUrl } = this.query;
        this.set("Content-Type", "image/jpg");
        this.body = got.stream.get(imageUrl);
    }

    /**
     * @api {get} /home/public/wxQrcodeLogin 微信二维码登录
     * @apiDescription 获取微信图片
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiParam {String} uid 用户uuid
     *
     * @apiSampleRequest /home/public/wxQrcodeLogin
     */
    async wxQrcodeLogin() {
        const { uid } = this.query;
        if (!uid) {
            return;
        }

        const api = new API(process.env.WX_APPID, process.env.WX_APPSECRET);
        const ticket = await api.createTmpQRCode(`login_${uid}`, 1800);
        const qrcodeUrl = await api.showQRCodeURL(ticket.ticket);

        this.set("Content-Type", "image/jpg");
        this.body = got.stream.get(qrcodeUrl);
    }

    /**
     *
     * @api {get} /home/wxa/code/getTemplateWxaQrcode 获取小程序码
     * @apiDescription 获取小程序码
     * @apiGroup App Home
     * @apiVersion 0.0.1
     *
     * @apiHeader {String} WxaToken 小程序授权token
     *
     * @apiParam {String} scene 场景值
     * @apiParam {String} page 小程序跳转链接
     *
     * @apiSampleRequest /home/wxa/code/getTemplateWxaQrcode
     */
    async getTemplateWxaQrcode() {
        const { id } = this.query;
        const { scene = "welcome", page } = this.query;

        const project = await this.model("diy_project")
            .query(qb => {
                qb.where("id", id);
            })
            .fetch();
        const app = await this.model("app")
            .query(qb => {
                qb.where("id", project.app_id);
            })
            .fetch();
        let wxa = await this.model("wxa")
            .query(qb => {
                qb.where("app_id", app.id);
            })
            .fetch();

        const code = new Code(
            process.env.OPEN_APPID,
            process.env.OPEN_APPSECRET
        );
        try {
            wxa = await this.checkWxaAuthorizerAccessToken(wxa);
        } catch (err) {
            this.status = 500;
            throw err;
        }
        this.ctx.set(
            "Content-disposition",
            `attachment; filename=${wxa.user_name}.jpg`
        );
        this.body = code.getWxaQrcodeUnlimit(
            wxa.authorizer_access_token,
            scene,
            page
        );
    }
};
